#include "AccCon.h"
#include "ComDef.h"
#include "CenterSvr.h"
#include "ProtoDispatch.h"
#include "Account.h"
#include "encrypt.h"
#include "scope_guard.h"
#include "Game.pb.h"
#include "CenterPlayer.h"

using namespace su;
using namespace std;
using namespace proto;


bool AccCon::Init()
{
	AdFacadeInitData d;
	d.mainCmd = (uint16)SvrType::Center;
	d.svrId = gCenterSvr.Cfg().svrId;
	d.vecAccAddr = gCenterSvr.Cfg().vecAcc;
	d.isVerifySvr = true;
	for (auto& v : d.vecAccAddr)
	{
		LDEBUG("con to access ", v.ip, v.port);
	}
	return ADFacadeMgr::Ins().Init(*this, d);
}

void AccCon::OnRevVerifyReq(const proto::SessionId& tmpSnId, uint32 cmd, const std::string& msg)
{
	bool IsOk = false;
	SCOPE_GUARD(
		if(!IsOk)
		{
			LDEBUG("con verify fail");
			ADFacadeMgr::Ins().NtfVerifyRet(tmpSnId, false);
		}
	);
	L_COND_V(cmd == GET_ACCOUNT_INFO_CMD);
	if(!gCenterSvr.m_readySet.all())
	{
		LWARN("center not ready");
		return;
	}
	LDEBUG("check con acc signature");
	GetAccountInfoReq req;
	L_COND_V(req.ParseFromString(msg));
	const LoginToken& token = req.token();
	string src = token.name() + StrNum::NumToStr(token.timestamp());
	string signature;
	Encrypt::encryptByHmacSha1(HMAC_SHA_KEY, src, signature);
	W_COND_V(signature == token.signature(), "check HmacSha1 fail. my, req=", signature, token.signature());

	time_t span = SysTime::Ins().Sec() - token.timestamp();
	if (span<0 || span>60*60*24)
	{
		string timeStr;
		SysTime::TimeToTimeStr(token.timestamp(), timeStr);
		LWARN("signature expire, time=", timeStr, " cur svr time=", SysTime::Ins().GetTimeStr());
		return;
	}
	
	if (ADFacadeMgr::Ins().SessionNum() >= MAX_LOGIN_PLAYER)
	{
		return;
	}

	LDEBUG("con acc verify ok");
	IsOk = true;
	ADFacadeMgr::Ins().NtfVerifyRet(tmpSnId, true);
	AccountMgr::Ins().GetAccountInfo(tmpSnId.accId, tmpSnId.cid, token.name());
}

void AccCon::OnRevClientMsg(const proto::Session& session, uint32 cmd, const std::string& msg)
{
	ProtoDispatch::Ins().Dispatch(session, cmd, msg);
}

void AccCon::OnClientDisCon(const proto::Session& sn)
{
	if (Account* acc = sn.GetWeakEx<Account>())
	{
		acc->TryRelease(true);
	}
}
